package net.jumpengine.util;

import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import javafx.scene.image.Image;
import net.jumpengine.Manager;

/**
 * 关于文件加载工具类
 * <br /><br />
 * <b>作者:&nbsp;</b>张天文 <br />
 * <b>日期:&nbsp;</b>2020年8月5日 下午3:29:03<br />
 * @date
 */
public class UIO {
	private UIO() {}
	
	/**
	    * 从文件路径中截取目录
	 * @param filePath 文件路径
	 * @return 目录路径
	 */
	public static String fileDirectory(String filePath){
		if(UComm.isNull(filePath))return "";
		int ind=filePath.lastIndexOf('/');
		if(ind<0)ind=filePath.lastIndexOf('\\');
		if(ind<0){
			return "";
		}else{
			return filePath.substring(0,ind);
		}
	}
	
	/**
	   * 获取类的来源定位
	 * @param c 类,不能为空
	 * @return 类的来源定位
	 */
	public static URL getSource(Class<?> c) {
		return c.getProtectionDomain().getCodeSource().getLocation();
	}
	
	/**
	  * 从图片配置文件中读取图片,配置例子: map.side=/img/map_side.png 
	 * @param propertiesPath 配置文件路径,可以为相对项目的路径或者jar包中路径
	 * @param perfix 过滤词, 以此开头的配置才会被读取, null为全部读取
	 * @param c 当前项目中的一个类,用于确定资源位置
	 * @return {配置key:value地址的图片}
	 */
	public static Map<String,Image> loadImageByPro(String propertiesPath,String perfix,Class<?> c){
		InputStream stream = loadFile(propertiesPath, c);
		Properties pro=new Properties();
		try {
			pro.load(stream);
		} catch (IOException e) {
			e.printStackTrace();
		}
		Enumeration<?> propertyNames = pro.propertyNames();
		Map<String,Image> map=new HashMap<>();
		String tmp;
		while(propertyNames.hasMoreElements()) {
			tmp=(String) propertyNames.nextElement();
			
			if(!UComm.isNull(perfix) && tmp.startsWith(perfix)) {
				map.put(tmp, loadImage(pro.getProperty(tmp), c));
			}else {
				map.put(tmp, loadImage(pro.getProperty(tmp), c));
			}
		}
		return map;
	}
	
	/**
	 * 加载目录下的图片,可以是zip/jar包里的目录
	 * @param dict 目录路径,可以是zip/jar包里的目录
	 * @param c 与目录路径在同一模块的类模版,用于指明资源所在模块
	 * @return 图片集合
	 */
	public static List<Image> loadImages(String dict,Class<?> c){
		List<InputStream> loadFiles = loadFiles(dict, c,new String[] {"jpg","gif","png","jpeg","bmp"});
		List<Image> list=new ArrayList<>(loadFiles.size());
		for(InputStream is:loadFiles) {
			list.add(new Image(is));
		}
		return list;
	}
	
	/**
	 * 加载图片, 可以是相对路径,可以是zip/jar包里的路径
	 * @param file 可以是相对路径,可以是zip/jar包里的路径
	 * @param c 与目录路径在同一模块的类模版,用于指明资源所在模块
	 * @return 图片
	 */
	public static Image loadImage(String file,Class<?> c){
		InputStream is = loadFile(file,c);
		return new Image(is);
	}
	
	/**
         * 加载目录下的资源,可以是独立文件路径或zip/jar包里的目录
	 * @param dict 目录路径,可以是zip/jar包里的目录
	 * @param c 与目录路径在同一模块的类模版,用于指明资源所在模块
	 * @param extFilter 文件扩展名过滤数组,只读取包含字符串数组中某个开头的资源
	 * @return 资源列表的输出流
	 */
	public static List<InputStream> loadFiles(String dict,Class<?> c,String[] extFilter){
		c=c==null?UIO.class:c;
		URL url = getSource(c);
		List<InputStream> list=new ArrayList<>();
		if(url.getFile().endsWith(".jar")) {
			try {
				if(dict.startsWith("/") || dict.startsWith("\\"))dict=dict.substring(1);
				@SuppressWarnings("resource")
				ZipFile zip=new ZipFile(url.toString().substring(6));
				ZipEntry entry;
				Enumeration<? extends ZipEntry> entries = zip.entries();
				String name;
				while(entries.hasMoreElements()) {
					entry=entries.nextElement();
					name=entry.getName();
					if(name.startsWith(dict)) {
						boolean flag=false;
						if(extFilter!=null) {
							for(String s:extFilter) {
								flag=flag || name.endsWith(s);
							}
						}else {
							flag=true;
						}
						if(flag)list.add(zip.getInputStream(entry));
					}
				}
				return list;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		url=c.getResource(dict);
		File f=new File(url.toString().substring(6));
		if(!f.isDirectory()) {
			Manager.getLog().error(UIO.class,"UIO[loadFiles]path:", f.getPath(),"不是目录!");
			return null;
		}
		File[] listFiles = f.listFiles(new FileFilter() {
			String s;
			@Override
			public boolean accept(File pathname) {
				if(extFilter==null || extFilter.length==0)return true;
				s=pathname.getName().toLowerCase();
				boolean in=false;
				for(String ext:extFilter) {
					in = in || s.endsWith(ext);
				}
				return in;
			}
		});
		try {
			for(File file:listFiles) {
				list.add(new FileInputStream(file));
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return list;
	}
	
	/**
	  * 读取文件,可以是独立文件路径或zip/jar包里的目录
	 * @param file 文件路径
	 * @param c 与目录路径在同一模块的类模版,用于指明资源所在模块
	 * @return 当前文件的输出流
	 */
	public static InputStream loadFile(String file,Class<?> c) {
		c=c==null?UIO.class:c;
		URL url = getSource(c);
		InputStream is=null;
		if(url.getFile().endsWith(".jar")) {
			try {
				ZipFile zip=new ZipFile(url.getFile());
				ZipEntry entry = zip.getEntry(file);
				if(entry!=null) {
					is=zip.getInputStream(entry);
					zip.close();
				}
				return is;
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		url = c.getResource(file);
		try {
			is=new FileInputStream(url.getFile());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return is;
	}
}
